from binascii import unhexlify
from crcmod import mkCrcFun


# CRC16/CCITT
def crc16_ccitt(s):
    crc16 = mkCrcFun(0x11021, rev=True, initCrc=0x0000, xorOut=0x0000)
    return get_crc_value(s, crc16)


# CRC16/CCITT-FALSE
def crc16_ccitt_false(s):
    crc16 = mkCrcFun(0x11021, rev=False, initCrc=0xFFFF, xorOut=0x0000)
    return get_crc_value(s, crc16)


# CRC16/MODBUS
def crc16_modbus(s):
    crc16 = mkCrcFun(0x18005, rev=True, initCrc=0xFFFF, xorOut=0x0000)
    return get_crc_value(s, crc16)


# CRC16/XMODEM
def crc16_xmodem(s):
    crc16 = mkCrcFun(0x11021, rev=False, initCrc=0x0000, xorOut=0x0000)
    return get_crc_value(s, crc16)


# common func
def get_crc_value(s, crc16):
    data = s.replace(' ', '')
    crc_out = hex(crc16(unhexlify(data))).upper()
    str_list = list(crc_out)

    if len(str_list) == 5:
        str_list.insert(2, '0')  # 位数不足补0
    if len(str_list) == 4:
        str_list.insert(2, '0')  # 位数不足补0
        str_list.insert(2, '0')  # 位数不足补0
    crc_data = ''.join(str_list[2:])
    return crc_data[:2] + ' ' + crc_data[2:]
    # return crc_data[2:] + ' ' + crc_data[:2]

def crc_verification(command: bytes) -> int: # crc验证

    protocol_code = command[1:5]

    args_length =  command[5: 7]

    args_length = args_length[0]<<8|args_length[1]

    args = command[7: 7+args_length]

    crc = command[-2:].hex()

    print("解析CRC：{}".format(crc16_xmodem(command[1:-2].hex()).upper().strip().replace(" ", "")))
    print("原CRC：{}".format(crc))
    
    return crc16_xmodem(command[1:-2].hex()).upper().strip() == crc


if __name__ == '__main__':
    # s1 = crc16_ccitt("6001")
    # s2 = crc16_ccitt_false("6001")
    # s3 = crc16_modbus("6001")
    # s4 = crc16_xmodem("00010210 001B 00000001 01 01 0010 01 0020 60E2801160600002094ED74AA6 02 0006")
    # print('crc16_ccitt: ' + s1)
    # print('crc16_ccitt_false: ' + s2)
    # print('crc16_modbus: ' + s3)
    # print('crc16_xmodem: ' + s4)

    data = b'Z\x00\x01\x12\x00\x00\x18\x00\x0c\xe2\x80h\x94\x00\x00@,\x14h\xcc\xf40\x00\x01\x01T\x08\x00\r\xf72\x9e\x07'


    sl = "000112000018000ce28068940000402c1468d8f4300001011e08000df732" # 48 33

    sl = "000112000018000ce2806894000050222058c52b300001010c08000df53e" # 00 54

    print(crc16_modbus("e50101000012000000010000"))

    x = crc16_xmodem("0001021000050000000f01") # d7 88

    print(x)

    x = crc16_xmodem("000102100005000000c301") # 84 b1

    print(x)

    x = crc16_xmodem("000102100005000000CF01") # C1DC

    print(x)

    x = crc16_xmodem("000102100005000000DF01") # C2 AF

    print(x)

    x = crc16_xmodem("000102100005000000FF01") # C4 49

    print(x)

    x = crc16_xmodem("0001021000050000003601") # 68 85

    print(x)

    # crc_verification(b'Z\x00\x01\x12\x00\x00\x18\x00\x0c\xe2\x80h\x94\x00\x00@,\x14h\xcc\xf40\x00\x01\x01T\x08\x00\r\xf72\x9e\x07')